﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using CorporateGym.DAL;
using BLL.Exceptions;
using System.Globalization;
using BLL.Entities;


namespace BLL
{
    public class TraineeManager
    {
        private static TraineeManager m_This;
        private static readonly object sr_SyncObj = new Object();
        public List<CorporateGymDB.TraineeRow> traineesRows { get; set; }
        public static TraineeManager Instance
        {
            get
            {
                if (m_This == null)
                {
                    lock (sr_SyncObj)
                    {
                        if (m_This == null)
                        {
                            m_This = new TraineeManager();
                        }
                    }
                }

                return m_This;
            }
        }

        private TraineeManager()
        {
        }

        public bool UpdateTrainee(Trainee i_Trainee)
        {
            return DataAccess.Instance.UpdateTrainee(
                i_Trainee.TraineeId,
                i_Trainee.WorkerId,
                i_Trainee.FirstName,
                i_Trainee.LastName,
                i_Trainee.Phone,
                i_Trainee.Email,
                (int)i_Trainee.WorkerType,
                i_Trainee.MedicalApprovalId);
        }

        public int AddTrainee(Trainee i_Trainee)
        {
            if (i_Trainee.TraineeId == 0)
            {
                return DataAccess.Instance.AddTrainee(
                    i_Trainee.WorkerId,
                    i_Trainee.FirstName,
                    i_Trainee.LastName,
                    i_Trainee.Phone,
                    i_Trainee.Email,
                    (int)i_Trainee.WorkerType,
                    i_Trainee.MedicalApprovalId);
            }
            else
            {
                if (UpdateTrainee(i_Trainee) == true)
                {
                    return i_Trainee.TraineeId;
                }
                else
                {
                    return 0;
                }
            }
        }

        public List<Trainee> GetTraineesByName(string i_Search)
        {
            List<Trainee> traineesResult = new List<Trainee>();
            var traineesRows = DataAccess.Instance.GetAllTrainees(i_Search);
            foreach (var traineeRow in traineesRows)
            {
                Trainee trainee = Trainee.CreateFromRow(traineeRow);
                traineesResult.Add(trainee);
            }

            return traineesResult;
        }

        public void MarkAsVisit(Trainee i_Trainee)
        {
            
            CorporateGym.DAL.CorporateGymDB.TraineeRow traineeRow = DataAccess.Instance.GetTraineeById(i_Trainee.TraineeId);
            int medicalApprovalId = traineeRow.MedicalApprovalId;
            CorporateGym.DAL.CorporateGymDB.MedicalApprovalRow medicalApprovalRow = DataAccess.Instance.GetMediaclApprovalById(medicalApprovalId);
            DateTime traineeExp = medicalApprovalRow.ExpirationDate;

            EWorkerType traineeType = i_Trainee.WorkerType;
            CorporateGymDB.PaymentsRow paymentRow = DataAccess.Instance.GetPayment(i_Trainee.TraineeId, DateTime.Now.Month, DateTime.Now.Year);
            
            CorporateGym.DAL.CorporateGymDB.TraineeVisitRow traineeLastVisitRow = DataAccess.Instance.GetLastVisitingByTraineeId(i_Trainee.TraineeId);
            if (traineeLastVisitRow != null)
            {
                int lastVisitYear = traineeLastVisitRow.StratingHour.Year;
                int lastVisitMonth = traineeLastVisitRow.StratingHour.Month;
                int lastVisitDay = traineeLastVisitRow.StratingHour.Day;

                if (lastVisitYear == DateTime.Now.Year && lastVisitMonth == DateTime.Now.Month && lastVisitDay == DateTime.Now.Day)
                {
                    throw new VisitedTodayException();
                }
            }
            
            if (DateTime.Compare( medicalApprovalRow.ExpirationDate , DateTime.Now) < 0)
            {
                throw new MedicalApprovalExpiredException();
            }
            else if (paymentRow == null && traineeType == EWorkerType.OutSource)
            {
                throw new PaymentException();
            }

            DataAccess.Instance.AddTraineeVisit(i_Trainee.TraineeId);
            UpdateAbsenseNotification(i_Trainee, false);
        }

        public DateTime? GetLastVisiting(int i_TraineeId)
        {
            DateTime? last = null;

            CorporateGymDB.TraineeVisitRow row = DataAccess.Instance.GetLastVisitingByTraineeId(i_TraineeId);
            if (row != null)
            {
                last = row.StratingHour;
            }

            return last;
        }

        public bool RemoveTrainee(Trainee i_Trainee)
        {
            return DataAccess.Instance.DeleteTraineeById(i_Trainee.TraineeId);
        }

        public bool AddPayment(Trainee i_Trainee, int i_Month, int i_Year)
        {
            bool isAddSucceeded = false;
            CorporateGymDB.PaymentsRow paymentRow = DataAccess.Instance.GetPayment(i_Trainee.TraineeId, i_Month, i_Year);
            if (paymentRow == null)
            {
                isAddSucceeded = DataAccess.Instance.AddPayment(i_Trainee.TraineeId, i_Month, i_Year);
            }

            return isAddSucceeded;
        }

        public static List<Payment> GetTraineePaymentHistory(int i_traineeId)
        {
            List<Payment> traineePayements = new List<Payment>();
            CorporateGymDB.PaymentsRow[]  paymentsRows = DataAccess.Instance.GetTraineePaymentHistory(i_traineeId);
            for (int i = 0; i < paymentsRows.Length; i++)
            {
                Payment payment = Payment.CreateFromRow(paymentsRows[i]);
                traineePayements.Add(payment);
            }

            return traineePayements;
        }

        public List<Trainee> GetTrainees()
        {
            return (from row in DataAccess.Instance.GetAllTrainees(string.Empty)
                    select Trainee.CreateFromRow(row)).ToList();
        }

        public List<GymVisit> GetVisits(Trainee i_Trainee)
        {
            return (from row in DataAccess.Instance.GetVisitsByTraineeId(i_Trainee.TraineeId)
                    select GymVisit.CreateFromRow(row)).ToList();
        }

        public void RemovePayment(Payment selectedPayment)
        {
            DataAccess.Instance.RemovePayment(selectedPayment.TraineeId, selectedPayment.Month, selectedPayment.Year);
        }

        public void UpdateAbsenseNotification(Trainee i_Trainee, bool i_NewVal)
        {
            i_Trainee.AbsenseNotificationSent = i_NewVal;
            DataAccess.Instance.AbsenseNotification(i_Trainee.TraineeId, false);
        }
    }
}
